/*
********************************************************************************
* Copyright (C) 2021, xiang.D <dx_65535@163.com>.
* All right reserved.
*
* File Name   : factory_method.cc
* Author      :
* Version     : V1.0
* Description :
* Journal     : 2021-10-10 init v1.0
* Brief       : Blog: https://blog.csdn.net/qq_38750572?spm=1001.2014.3001.5343
* Others      :
********************************************************************************
*/
#include <iostream>

using namespace std;

/* Phone abstract interface */
class CPhone
{
public:

    virtual ~CPhone() {}

    /* Function interface for phone */
    virtual void showLabel() = 0;
    virtual void call() = 0;
    virtual void takePicture() = 0;
    virtual void messages() = 0;
};

class CHwMate : public CPhone
{
public:

    void showLabel()
    {
        cout << "Welcome To Mate Phone!" << endl;
    }

    void call() {}
    void takePicture() {}
    void messages() {}
};

class CHwNova : public CPhone
{
public:

    void showLabel()
    {
        cout << "Welcome To Nova Phone!" << endl;
    }

    void call() {}
    void takePicture() {}
    void messages() {}
};
/* End Phone implementation */

/* Watch abstract interface */
class CWatch
{
public:

    virtual ~CWatch() {}

    /* Function interface for watch */
    virtual void showLabel() = 0;
    virtual void timer() = 0;
    virtual void alarms() = 0;
};

class CHwGt2 : public CWatch
{
public:

    void showLabel()
    {
        cout << "Be happy every day wearing Gt2!" << endl;
    }

    void timer() {}
    void alarms() {}
};

class CHwGt2Pro : public CWatch
{
public:

    void showLabel()
    {
        cout << "Be happy every day wearing Gt2Pro!" << endl;
    }

    void timer() {}
    void alarms() {}
};
/* End watch implementation */

/* Factory abstract interface */
class CHuaWeiBusiness
{
public:

    /* Production interface for phone production */
    virtual CPhone *getPhoneInstance() = 0;

    /* Production interface for watch production */
    virtual CWatch *getWatchInstance() = 0;
};

class CHwMateProducer : public CHuaWeiBusiness
{
public:

    CHwMate *getPhoneInstance()
    {
        return new CHwMate();
    }

    /* Adding Watch Gt2Pro interface */
    CHwGt2Pro *getWatchInstance()
    {
        return new CHwGt2Pro();
    }
};

class CHwNovaProducer : public CHuaWeiBusiness
{
public:

    /* Production interface list */
    CHwNova *getPhoneInstance()
    {
        return new CHwNova();
    }

    CHwGt2 *getWatchInstance()
    {
        return new CHwGt2();
    }
};
/* End factory abstract interface */


int main(int argc, char *argv[])
{
    /* Production form Mate Producer */
    cout << "--> Mate Procducer" << endl;
    CHwMateProducer theHwMateProducer;
    CPhone *thePhoneFromMate = theHwMateProducer.getPhoneInstance();
    if (NULL != thePhoneFromMate) {
        thePhoneFromMate->showLabel();
        delete thePhoneFromMate;
    } else {
        cout << "thePhoneFromMate is NULL!" << endl;
    }
    CWatch *theWatchFromMate = theHwMateProducer.getWatchInstance();
    if (NULL != thePhoneFromMate) {
        thePhoneFromMate->showLabel();
        delete theWatchFromMate;
    } else {
        cout << "thePhoneFromMate is NULL!" << endl;
    }

    /* Production form Nova Producer */
    cout << "--> Nova Procducer" << endl;
    CHwNovaProducer theHwNovaProducer;
    CPhone *thePhoneFromNova = theHwNovaProducer.getPhoneInstance();
        if (NULL != thePhoneFromNova) {
        thePhoneFromNova->showLabel();
        delete thePhoneFromNova;
    } else {
        cout << "thePhoneFromNova is NULL!" << endl;
    }
    CWatch *theWatchFromNova = theHwNovaProducer.getWatchInstance();
    if (NULL != theWatchFromNova) {
        theWatchFromNova->showLabel();
        delete theWatchFromNova;
    } else {
        cout << "theWatchFromNova is NULL!" << endl;
    }

    return 0;
}

